﻿
using CSharpLibs.Annotations;

namespace System.IO
{
	[Builtin]
	public class BinaryWriter : IDisposable
	{
		private byte[] m_buffer;
		protected Stream OutStream;

		protected BinaryWriter()
		{
			this.m_buffer = new byte[0x10];
			this.OutStream = null;
		}

		public BinaryWriter(Stream output)
		{
			this.m_buffer = new byte[0x10];
			this.OutStream = output; 
		}

		[BuiltinMethod, BuiltinSemantics("binaryconv_fromdouble")]
		private static ulong ConvertDoubleToBitRepresentation(double d)
		{ return 0; }

		[BuiltinMethod, BuiltinSemantics("binaryconv_fromfloat")]
		private static uint ConvertSingleToBitRepresentation(float f)
		{ return 0; }

		public virtual void Close()
		{ this.Dispose(true); }

		public void Dispose()
		{ this.Dispose(true); }

		protected virtual void Dispose(bool disposing)
		{
			if(disposing)
				this.OutStream.Close();
		}

		public virtual long Seek(int offset, SeekOrigin origin)
		{ return this.OutStream.Seek((long)offset, origin); }

		public virtual void Write(bool value)
		{
			this.m_buffer[0] = value ? ((byte)1) : ((byte)0);
			this.OutStream.Write(this.m_buffer, 0, 1);
		}

		public virtual void Write(byte value)
		{ this.OutStream.WriteByte(value); }

		public virtual void Write(sbyte value)
		{ this.OutStream.WriteByte((byte)value); }

		public virtual void Write(byte[] buffer)
		{ this.OutStream.Write(buffer, 0, buffer.Length); }

		public virtual void Write(char ch)
		{ this.OutStream.WriteByte((byte)ch); }

		public virtual void Write(char[] chars)
		{
			byte[] buffer = new byte[chars.Length];
			for(int i = 0; i < chars.Length; ++i)
				buffer[i] = (byte)chars[i];

			this.OutStream.Write(buffer, 0, buffer.Length);
		}

		public virtual void Write(double value)
		{
			ulong bv = ConvertDoubleToBitRepresentation(value);
			this.Write(bv);
		}

		public virtual void Write(short value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.OutStream.Write(this.m_buffer, 0, 2);
		}

		public virtual void Write(int value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.m_buffer[2] = (byte)(value >> 0x10);
			this.m_buffer[3] = (byte)(value >> 0x18);
			this.OutStream.Write(this.m_buffer, 0, 4);
		}

		public virtual void Write(long value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.m_buffer[2] = (byte)(value >> 0x10);
			this.m_buffer[3] = (byte)(value >> 0x18);
			this.m_buffer[4] = (byte)(value >> 0x20);
			this.m_buffer[5] = (byte)(value >> 40);
			this.m_buffer[6] = (byte)(value >> 0x30);
			this.m_buffer[7] = (byte)(value >> 0x38);
			this.OutStream.Write(this.m_buffer, 0, 8);
		}

		public virtual void Write(float value)
		{
			uint bv = ConvertSingleToBitRepresentation(value);
			this.Write(bv);
		}

		public virtual void Write(ushort value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.OutStream.Write(this.m_buffer, 0, 2);
		}

		public virtual void Write(uint value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.m_buffer[2] = (byte)(value >> 0x10);
			this.m_buffer[3] = (byte)(value >> 0x18);
			this.OutStream.Write(this.m_buffer, 0, 4);
		}

		public virtual void Write(ulong value)
		{
			this.m_buffer[0] = (byte)value;
			this.m_buffer[1] = (byte)(value >> 8);
			this.m_buffer[2] = (byte)(value >> 0x10);
			this.m_buffer[3] = (byte)(value >> 0x18);
			this.m_buffer[4] = (byte)(value >> 0x20);
			this.m_buffer[5] = (byte)(value >> 40);
			this.m_buffer[6] = (byte)(value >> 0x30);
			this.m_buffer[7] = (byte)(value >> 0x38);
			this.OutStream.Write(this.m_buffer, 0, 8);
		}

		public virtual void Write(byte[] buffer, int index, int count)
		{ this.OutStream.Write(buffer, index, count); }

		public virtual void Write(char[] chars, int index, int count)
		{
			byte[] buffer = new byte[count];
			for(int i = 0; i < count; ++i)
				buffer[i] = (byte)chars[index + i];

			this.OutStream.Write(buffer, 0, buffer.Length);
		}

		public virtual Stream BaseStream
		{ get { return this.OutStream; } }
	}
}
